/*
 * Copyright (C) 2012, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.store.loaders;

/**
 *
 * @author Laurent WOUTERS
 */
public class Automaton {
    static final int NO_TRANSITION = 0xFFFF;
    
    private static class State {
        private int terminal;
        private int[] cache;
        private int[][] transitions;
        public int getTerminal() { return terminal; }
        public int getTransition(char key) {
            if (key < 256) return cache[key];
            for (int i=0; i!=transitions.length; i++)
                if (key >= transitions[i][0] && key <= transitions[i][1])
                    return transitions[i][2];
            return NO_TRANSITION;
        }
        public State(BinaryStream stream) throws java.io.IOException {
            terminal = stream.readShort();
            int count = stream.readShort();
            cache = new int[256];
            transitions = new int[count][];
            for (int i=0; i!=256; i++)
                cache[i] = stream.readShort();
            for (int i=0; i!=count; i++) {
                int[] t = new int[3];
                t[0] = stream.readShort();
                t[1] = stream.readShort();
                t[2] = stream.readShort();
                transitions[i] = t;
            }
        }
    }
    
    private State[] states;

    private Automaton(java.io.InputStream stream)
    {
        BinaryStream input = new BinaryStream(stream);
        try {
            int count = input.readInt();
            input.skipBytes(count * 4);
            states = new State[count];
            for (int i=0; i!=count; i++)
                states[i] = new State(input);
        } catch (java.io.IOException ex) { }
    }
    
    public static Automaton load(String resource) {
        java.lang.ClassLoader loader = java.lang.ClassLoader.getSystemClassLoader();
        java.io.InputStream stream = loader.getResourceAsStream(resource);
        Automaton result = new Automaton(stream);
        try { stream.close(); }
        catch(java.io.IOException ex) { }
        return result;
    }
    
    public int getTerminal(int state) { return states[state].getTerminal(); }
    public int getTransition(int state, char key) { return states[state].getTransition(key); }
}
